package com.lcxw.hxzbim.netty.server;

import com.lcxw.hxzbim.netty.model.CIMConstant;
import com.lcxw.hxzbim.netty.model.CIMConstant.ProtobufType;
import com.lcxw.hxzbim.netty.model.Message;
import com.lcxw.hxzbim.netty.model.proto.MessageProto;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.AttributeKey;
import java.util.List;
import com.lcxw.hxzbim.netty.model.CIMSession;
import com.lcxw.hxzbim.netty.model.SentBody;
import com.lcxw.hxzbim.netty.model.proto.SentBodyProto;

/**
 * 服务端接收来自应用的消息解码
 */
public class AppMessageDecoder extends ByteToMessageDecoder {

	@Override
	public void decode(ChannelHandlerContext arg0, ByteBuf buffer, List<Object> queue) throws Exception {

		/**
		 * 消息头3位
		 */
		if (buffer.readableBytes() < CIMConstant.DATA_HEADER_LENGTH) {
			return;
		}

		buffer.markReaderIndex();

		byte conetnType = buffer.readByte();

		byte lv = buffer.readByte();// int 低位
		byte hv = buffer.readByte();// int 高位

		int conetnLength = getContentLength(lv, hv);

		// 如果消息体没有接收完整，则重置读取，等待下一次重新读取
		if (conetnLength <= buffer.readableBytes()) {
			byte[] dataBytes = new byte[conetnLength];
			buffer.readBytes(dataBytes);

			Object message = mappingMessageObject(dataBytes, conetnType);
			if (message != null) {
				arg0.channel().attr(AttributeKey.valueOf(CIMSession.PROTOCOL)).set(CIMSession.NATIVEAPP);
				queue.add(message);
				return;
			}
		}

		buffer.resetReaderIndex();
	}

	public Object mappingMessageObject(byte[] data, byte type) throws Exception {

		if (CIMConstant.ProtobufType.C_H_RS == type) {
			SentBody body = new SentBody();
			body.setKey(CIMConstant.CLIENT_HEARTBEAT);
			body.setTimestamp(System.currentTimeMillis());
			return body;
		}

		if (CIMConstant.ProtobufType.SENTBODY == type) {
			SentBodyProto.Model bodyProto = SentBodyProto.Model.parseFrom(data);
			SentBody body = new SentBody();
			body.setKey(bodyProto.getKey());
			body.setTimestamp(bodyProto.getTimestamp());
			body.putAll(bodyProto.getDataMap());

			return body;
		}

		if (ProtobufType.MESSAGE == type) {
			MessageProto.Model bodyProto = MessageProto.Model.parseFrom(data);
			Message message = new Message();
			message.setAction(bodyProto.getAction());
			message.setContent(bodyProto.getContent());
			message.setExtra(bodyProto.getExtra());
			message.setFormat(bodyProto.getFormat());
			message.setId(bodyProto.getId());
			message.setReceiver(bodyProto.getReceiver());
			message.setSender(bodyProto.getSender());
			message.setTimestamp(bodyProto.getTimestamp());
			message.setTitle(bodyProto.getTitle());

			return message;
		}

		return null;
	}

	/**
	 * 解析消息体长度
	 * 
	 * @return
	 */
	private int getContentLength(byte lv, byte hv) {
		int l = (lv & 0xff);
		int h = (hv & 0xff);
		return (l | (h <<= 8));
	}
}
